﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ProgramUpDate
{
    public partial class ProgramUpDate : Form
    {
        string app_id = string.Empty;//应用程序id
        string app_version = string.Empty;//在线版本
        string app_name = string.Empty;//应用程序名称
        string app_exe_name = string.Empty;//应用程序主程序名称
        string app_fold_name = string.Empty;//应用程序主程序所在文件夹
        string MACHINE_ID = string.Empty;
        string FtpServerIP = "172.19.41.112";
        string FtpUserID = "administrator";
        string FtpPassword = "Qazwsx123";
        string PROCESS_NAME = string.Empty;
        FtpHelp ftpHelp;
        DataTable dt_ReleaseInfo = new DataTable();
        Base64Help base64 = new Base64Help();
        int com_version = 0;
        public ProgramUpDate()
        {
            InitializeComponent();
        }

        private void ProgramUpDate_Load(object sender, EventArgs e)
        {
            try
            {
                //获取电脑信息
                HostInfoHelp hostInfoHelp = new HostInfoHelp();
                string ip = hostInfoHelp.GetLocalIP();
                string mac = hostInfoHelp.GetMacByIpConfig();
                string mac_name = hostInfoHelp.getHostName();
                //初始化FTP信息
                FtpServerIP = Readjson("FtpServerIP");
                FtpUserID = Readjson("FtpUserID");
                FtpPassword = Readjson("FtpPassword");
                ftpHelp = new FtpHelp(FtpServerIP, FtpUserID, FtpPassword);
                //初始化数据库链接信息
                OracleHelper.ConnectionString_Default = base64.DecodeBase64(Readjson("link_config"));
                //初始化dt_ReleaseInfo
                dt_ReleaseInfo.Columns.Add("version");
                dt_ReleaseInfo.Columns.Add("ReleaseTime");
                dt_ReleaseInfo.Columns.Add("FileCount");
                dt_ReleaseInfo.Columns.Add("ReleaseNote");
                dt_ReleaseInfo.Columns.Add("APP_RELEASE_RECORD_ID");
                string aFoldName = string.Empty;
                //获取应用程序信息
                string[] StartupPath = Application.StartupPath.ToString().Split('\\');
                aFoldName = StartupPath[StartupPath.Count() - 1];                

                string sql = string.Format("select * from APPLICATION where FOLD_NAME = '{0}'", aFoldName);
                DataTable dt_APPLICATION = OracleHelper.ExecuteDataTable(sql);
                if (dt_APPLICATION.Rows.Count > 0)
                {
                    if (dt_APPLICATION.Rows.Count != 1)
                    {
                        MessageBox.Show(string.Format("根据文件夹名称【{0}】找到了多个应用，请联系管理员！", aFoldName), "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                        this.Close();
                        return;
                    }
                    app_id = dt_APPLICATION.Rows[0]["APP_ID"].ToString();
                    app_version = dt_APPLICATION.Rows[0]["VERSION"].ToString();
                    app_name = dt_APPLICATION.Rows[0]["APP_NAME"].ToString();
                    app_exe_name = dt_APPLICATION.Rows[0]["APP_EXE_NAME"].ToString();
                    app_fold_name = dt_APPLICATION.Rows[0]["FOLD_NAME"].ToString();

                    string sql_Process = "select * from user_tab_columns where TABLE_NAME = 'APPLICATION' and COLUMN_NAME = 'PROCESS_NAME'";
                    DataTable dt_Process = OracleHelper.ExecuteDataTable(sql_Process);
                    if (dt_Process.Rows.Count > 0)
                    {
                        PROCESS_NAME = dt_APPLICATION.Rows[0]["PROCESS_NAME"].ToString();
                    }
                }
                else
                {
                    MessageBox.Show(string.Format("根据文件夹名称【{0}】没有找到相应的升级程序", aFoldName), "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    this.Close();
                    return;
                }
                //获取电脑信息
                sql = string.Format("select c.* from computer c join machine m on c.machine_id = m.machine_id where MACHINE_NAME = '{0}' and MAC_ADDR = '{1}'", mac_name, mac);
                DataTable dt_COMPUTER = OracleHelper.ExecuteDataTable(sql);
                if (dt_COMPUTER.Rows.Count == 1)
                {
                    MACHINE_ID = dt_COMPUTER.Rows[0]["MACHINE_ID"].ToString();
                    sql = string.Format("select * from COMPUTER_X_APP_VER where MACHINE_ID = '{0}' and APP_ID = '{1}'", dt_COMPUTER.Rows[0]["MACHINE_ID"], app_id);
                    DataTable dt_COMPUTER_X_APP_VER = OracleHelper.ExecuteDataTable(sql);
                    if (dt_COMPUTER_X_APP_VER.Rows.Count == 1)
                    {
                        com_version = int.Parse(dt_COMPUTER_X_APP_VER.Rows[0]["VERSION"].ToString());
                        Init(int.Parse(dt_COMPUTER_X_APP_VER.Rows[0]["VERSION"].ToString()));
                    }
                    else if (dt_COMPUTER_X_APP_VER.Rows.Count == 0)
                    {
                        //InitProgram(); //拉取程序
                        //拉取程序成功后插入COMPUTER_X_APP_VER表
                        string COMPUTER_X_APP_VER_ID = OracleHelper.ExecuteDataTable("select COMPUTER_X_APP_VER_SEQ.nextval from dual").Rows[0]["nextval"].ToString();
                        stringBuilder insert_COMPUTER_X_APP_VER = new stringBuilder(@"
                    INSERT INTO COMPUTER_X_APP_VER
                        (COMPUTER_X_APP_VER_ID,APP_ID,MACHINE_ID,VERSION)
                        VALUES").appendFirst(COMPUTER_X_APP_VER_ID).append(app_id).append(dt_COMPUTER.Rows[0]["MACHINE_ID"]).appendLast(0);
                        int result_count = OracleHelper.ExecuteNonQuery(insert_COMPUTER_X_APP_VER.ToString());
                        if (result_count == 0)
                        {
                            MessageBox.Show("插入COMPUTER表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                            this.Close();
                            return;
                        }
                        //StartProgram(); //启动程序
                        //this.Close();
                        Init(0);
                        return;
                    }
                    else
                    {

                        MessageBox.Show("客户端电脑信息异常", $"COMPUTER_X_APP_VER（MACHINE_ID：{dt_COMPUTER.Rows[0]["MACHINE_ID"]}）查询到多条信息", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                        this.Close();
                        return;
                    }
                }
                else if (dt_COMPUTER.Rows.Count == 0)
                {
                    //将电脑信息插入MACHINE、COMPUTER
                    //插入MACHINE
                    MACHINE_ID = OracleHelper.ExecuteDataTable("select MACHINE_SEQ.nextval from dual").Rows[0]["nextval"].ToString();
                    stringBuilder insert_MACHINE = new stringBuilder(@"
                    INSERT INTO MACHINE
                        (MACHINE_ID,MACHINE_NAME,MACHINE_TYPE_CODING,ENABLED_FLAG,MACHINE_ALIAS)
                        VALUES").appendFirst(MACHINE_ID).append(mac_name).append("1").append("1").appendLast("");
                    int result_count = OracleHelper.ExecuteNonQuery(insert_MACHINE.ToString());
                    if (result_count == 0)
                    {
                        MessageBox.Show("插入MACHINE表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                        return;
                    }
                    //插入COMPUTER
                    stringBuilder insert_COMPUTER = new stringBuilder(@"
                    INSERT INTO COMPUTER
                        (MACHINE_ID,IP_ADDR,MAC_ADDR)
                        VALUES").appendFirst(MACHINE_ID).append(ip).appendLast(mac);
                    result_count = OracleHelper.ExecuteNonQuery(insert_COMPUTER.ToString());
                    if (result_count == 0)
                    {
                        MessageBox.Show("插入COMPUTER表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                        this.Close();
                        return;
                    }
                    ////将服务器上的程序整个拉取到当前文件夹下
                    //if (!ftpHelp.CheckFtp())
                    //{
                    //    MessageBox.Show("FTP连接失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    //    this.Close();
                    //    return;
                    //}
                    //InitProgram(); //拉取程序
                    //拉取程序成功后插入COMPUTER_X_APP_VER表
                    string COMPUTER_X_APP_VER_ID = OracleHelper.ExecuteDataTable("select COMPUTER_X_APP_VER_SEQ.nextval from dual").Rows[0]["nextval"].ToString();

                    stringBuilder insert_COMPUTER_X_APP_VER = new stringBuilder(@"
                    INSERT INTO COMPUTER_X_APP_VER
                        (COMPUTER_X_APP_VER_ID,APP_ID,MACHINE_ID,VERSION)
                        VALUES").appendFirst(COMPUTER_X_APP_VER_ID).append(app_id).append(MACHINE_ID).appendLast(0);
                    result_count = OracleHelper.ExecuteNonQuery(insert_COMPUTER_X_APP_VER.ToString());
                    if (result_count == 0)
                    {
                        MessageBox.Show("插入COMPUTER表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                        this.Close();
                        return;
                    }
                    Init(0);
                    //StartProgram(); //启动程序
                    //this.Close();
                    return;
                }
                else
                {
                    MessageBox.Show("客户端电脑信息异常", $"IP_ADDR = '{ip}' and MAC_ADDR = '{mac}' 未查询到数据", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    this.Close();
                    return;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void Init(int version)
        {
            try
            {
                com_version = version;
                if (int.Parse(app_version) < version)
                {
                    MessageBox.Show(string.Format("客户端版本【{0}】大于服务端版本【{1}】异常", version, app_version), "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    this.Close();
                    return;
                }
                else if (int.Parse(app_version) == version)
                {
                    if (com_version != 0)
                    {
                        StartProgram(); //启动程序
                                        //if (com_version == 0)
                                        //{
                                        //    tsb_UpdateAll_Click(null,null);
                                        //}
                        this.Close();
                        return;
                    }
                    toolStripLabel1.Text = string.Format("当前客户端版本号为【{0}】，最新版本号为【{1}】，需要升级！", version, app_version);
                    return;
                }
                string sql = string.Format(@"select a.*,(select count(*) from APP_RELEASE_ITEM where APP_RELEASE_RECORD_ID = a.APP_RELEASE_RECORD_ID) as FileCount 
                                        from APP_RELEASE_RECORD a where APP_ID = '{0}' and VERSION > {1} and release_flag = 1 order by a.version asc", app_id, version);
                DataTable dt_APP_RELEASE_RECORD = OracleHelper.ExecuteDataTable(sql);
                if ((int.Parse(app_version) - version) < dt_APP_RELEASE_RECORD.Rows.Count)
                {
                    MessageBox.Show("应用程序发布记录数据异常！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    this.Close();
                    return;
                }
                else
                {
                    foreach (DataRow dr in dt_APP_RELEASE_RECORD.Rows)
                    {
                        DataRow drnew = dt_ReleaseInfo.NewRow();
                        drnew["version"] = dr["VERSION"];
                        drnew["ReleaseTime"] = dr["RELEASE_AT"];
                        drnew["FileCount"] = dr["FileCount"];
                        drnew["ReleaseNote"] = dr["RELEASE_NOTE"];
                        drnew["APP_RELEASE_RECORD_ID"] = dr["APP_RELEASE_RECORD_ID"];
                        dt_ReleaseInfo.Rows.Add(drnew);
                    }
                    dgv_ReleaseInfo.DataSource = dt_ReleaseInfo;
                    toolStripLabel1.Text = string.Format("当前客户端版本号为【{0}】，最新版本号为【{1}】，需要升级！", version, app_version);
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public static string Readjson(string key)
        {
            try
            {
                string strPath = System.Environment.CurrentDirectory + "\\config";
                string jsonfile = strPath + "\\FtpConfig.json";//JSON文件路径
                if (!Directory.Exists(strPath))
                {
                    //model.code = "-4";
                    //model.msg = "医保配置文件不存在 !" + jsonfile;
                }

                using (System.IO.StreamReader file = System.IO.File.OpenText(jsonfile))
                {
                    using (JsonTextReader reader = new JsonTextReader(file))
                    {
                        JObject o = (JObject)JToken.ReadFrom(reader);
                        var value = o[key].ToString();
                        return value;
                    }
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        List<string> files = new List<string>();
        public void GetFiles(string name)
        {
            try
            {
                string[] fullname = ftpHelp.GetFilesList(name);
                if (fullname.Count() == 0)
                    return;
                foreach (string str in fullname)
                {
                    string[] strs = str.Split('|');
                    if (strs[1] == "<DIR>")
                    {
                        GetFiles(name + strs[0] + "/");
                        //string dirctory = strs[3];
                    }
                    else
                    {
                        files.Add(name + strs[0]);
                    }
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private void StartProgram()
        {
            try
            {
                if (!File.Exists(Application.StartupPath + "\\" + app_exe_name))
                {
                    MessageBox.Show("未找到" + app_exe_name + "！当前机器版本为：" + com_version.ToString());
                    return;
                }
                Process process = new Process();
                process.StartInfo.FileName = Application.StartupPath + "\\" + app_exe_name;
                process.Start();
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private void tsb_Cancel_Click(object sender, EventArgs e)
        {
            try
            {
                StartProgram();
                this.Close();
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        
        private void tsb_Update_Click(object sender, EventArgs e)
        {
            int version_now = 0;
            if (com_version == 0 && !File.Exists(Application.StartupPath + "\\" + app_exe_name))
            {
                MessageBox.Show("当前机器版本为：" + com_version.ToString() + " 请先全量拉取程序！");
                return;
            }
            try
            {
                if (dgv_ReleaseInfo == null)
                {
                    return;
                }
                //升级前先杀掉进程
                Common.WriterLogs("升级前杀掉进程---开始", $"PROCESS_NAME:{PROCESS_NAME}");
                if (!string.IsNullOrEmpty(PROCESS_NAME))
                {
                    Process[] processes = Process.GetProcessesByName(PROCESS_NAME); 
                    foreach (Process process in processes) 
                    {
                        try
                        {
                            Common.WriterLogs("process.Kill", $"PROCESS_NAME:{process.ProcessName}");
                            process.Kill();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show($"进程：{PROCESS_NAME} 退出失败！失败原因：{ex.ToString()}");
                        }
                        
                    }
                }
                foreach (DataGridViewRow row in dgv_ReleaseInfo.Rows)
                {
                    if (int.Parse(row.Cells["version"].Value.ToString()) > version_now)
                    {
                        version_now = int.Parse(row.Cells["version"].Value.ToString());
                    }
                    string sql = string.Format("select * from APP_RELEASE_ITEM where APP_RELEASE_RECORD_ID = {0}", row.Cells["APP_RELEASE_RECORD_ID"].Value.ToString());
                    DataTable dt_APP_RELEASE_ITEM = OracleHelper.ExecuteDataTable(sql);
                    if (dt_APP_RELEASE_ITEM.Rows.Count > 0)
                    {
                        string UPDATE_RECORD_ID = OracleHelper.ExecuteDataTable("select UPDATE_RECORD_SEQ.nextval from dual").Rows[0]["nextval"].ToString();
                        stringBuilder insert_UPDATE_RECORD = new stringBuilder(@"
                    INSERT INTO UPDATE_RECORD
                        (UPDATE_RECORD_ID,APP_RELEASE_RECORD_ID，MACHINE_ID，UPDATE_AT，UPDATE_RECORD_STATUS)
                        VALUES").appendFirst(UPDATE_RECORD_ID).append(row.Cells["APP_RELEASE_RECORD_ID"].Value.ToString()).append(MACHINE_ID).append(DateTime.Now).appendLast("1");
                        Common.WriterLogs("process.Kill", $"PROCESS_NAME:{insert_UPDATE_RECORD.ToString()}");
                        int result_count = OracleHelper.ExecuteNonQuery(insert_UPDATE_RECORD.ToString());
                        if (result_count == 0)
                        {
                            MessageBox.Show("插入UPDATE_RECORD表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                            this.Close();
                            return;
                        }
                        foreach (DataRow dr in dt_APP_RELEASE_ITEM.Rows)
                        {
                            DirectoryInfo directory = Directory.CreateDirectory(Application.StartupPath);
                            //从ftp上拉取升级文件
                            Common.WriterLogs("FtpHelp.Download【文件下载】", dr["FILE_PATH"] + "/" + dr["FILE_NAME"]);
                            ftpHelp.Download(directory.Parent.FullName.ToString() + "\\" + dr["FILE_PATH"].ToString().Replace("/", "\\") + "\\" + dr["FILE_NAME"], dr["FILE_PATH"] + "/" + dr["FILE_NAME"], this.progressBar1);

                            string UPDATE_DETAIL_ID = OracleHelper.ExecuteDataTable("select UPDATE_DETAIL_SEQ.nextval from dual").Rows[0]["nextval"].ToString();
                            stringBuilder insert_UPDATE_DETAIL = new stringBuilder(@"
                    INSERT INTO UPDATE_DETAIL
                        (UPDATE_DETAIL_ID,UPDATE_RECORD_ID,FILE_NAME,FILE_PATH,UPDATE_STATUS,UPDATE_AT)
                        VALUES").appendFirst(UPDATE_DETAIL_ID).append(UPDATE_RECORD_ID).append(dr["FILE_NAME"]).append(dr["FILE_PATH"]).append("1").appendLast(DateTime.Now);
                            Common.WriterLogs("process.Kill", $"PROCESS_NAME:{insert_UPDATE_DETAIL.ToString()}");
                            result_count = OracleHelper.ExecuteNonQuery(insert_UPDATE_DETAIL.ToString());
                            if (result_count == 0)
                            {
                                MessageBox.Show("插入UPDATE_DETAIL表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                                this.Close();
                                return;
                            }
                        }
                    }
                    else
                    {
                        MessageBox.Show("不存在升级文件信息!", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                        return;
                    }
                }
                string update_APPLICATION = string.Format("update COMPUTER_X_APP_VER set VERSION = {0} where MACHINE_ID = {1} and APP_ID = {2}", version_now, MACHINE_ID, app_id);
                Common.WriterLogs("process.Kill", $"PROCESS_NAME:{update_APPLICATION}");
                int result_count1 = OracleHelper.ExecuteNonQuery(update_APPLICATION);
                if (result_count1 == 0)
                {
                    MessageBox.Show("更新COMPUTER_X_APP_VER表失败！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    return;
                }
                MessageBox.Show("升级成功！");
                if (version_now == int.Parse(app_version))
                {
                    this.Close();
                    StartProgram();
                }
                else
                {
                    toolStripLabel1.Text = string.Format("当前客户端版本号为【{0}】，最新版本号为【{1}】，需要升级！", version_now, app_version);
                }
            }
            catch (Exception ex)
            {
                Common.WriterLogs("升级程序异常", ex.ToString());
                throw ex;
            }
        }

        private void tsb_UpdateAll_Click(object sender, EventArgs e)
        {
            if (com_version != 0)
            {
                MessageBox.Show("当前机器已升级，请勿全量拉取！", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                return;
            }
            try
            {
                GetFiles(app_fold_name + "/");
                foreach (string file in files)
                {
                    DirectoryInfo directory = Directory.CreateDirectory(Application.StartupPath);
                    if (directory.Parent.FullName.ToString() + "\\" + file.ToString().Replace("/", "\\") != Application.StartupPath + "\\Newtonsoft.Json.dll" && directory.Parent.FullName.ToString() + "\\" + file.ToString().Replace("/", "\\") != Application.StartupPath + "\\Oracle.ManagedDataAccess.dll")
                    {
                        ftpHelp.Download(directory.Parent.FullName.ToString() + "\\" + file.ToString().Replace("/", "\\"), file, this.progressBar1);
                    }
                }
                MessageBox.Show("拉取成功！");
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
    }
}
